<template>
  <div>
    <table-header
      v-if="showTableHeader"
      v-bind="$attrs"
      :size="tableSize"
      v-on="$listeners"
      @set-size="setTableSize"
    >
      <div v-if="$slots.toolbar" slot="toolbar">
        <slot name="toolbar" />
      </div>
    </table-header>
    <div v-if="!showTableHeader && $slots.toolbar" class="table-btn">
      <slot name="toolbar" />
    </div>
    <el-table
      v-loading="loading"
      class="template-table"
      :stripe="stripe"
      :header-cell-style="{ background: '#fafafa', color: '#606266', textAlign: align }"
      :border="border"
      :data="datas"
      :height="height"
      :size="tableSize"
      :span-method="spanMethod"
      :row-class-name="markRow"
      :max-height="maxHeight"
      @sort-change="handleSortChange"
      @selection-change="handleSelectionChange"
    >
      <el-table-column
        v-if="selection"
        :align="align"
        :selectable="selectable"
        label="全选"
        type="selection"
      />
      <el-table-column
        v-if="isOrderNumber"
        :align="align"
        type="index"
        width="50"
      />
      <el-table-column v-if="hasExpandItem" :align="align" type="expand">
        <el-form slot-scope="{ row }" label-width="80px">
          <template
            v-for="{
              prop,
              label,
              isExpand,
              displayProp,
              enums,
              listComponent,
              isHtml
            } in configs"
          >
            <el-form-item v-if="isExpand" :key="prop" :label="label">
              <component
                :is="listComponent"
                v-if="listComponent"
                v-model="row[prop]"
                :data="row"
                :prop="prop"
                :enums="enums"
                v-bind="$attrs"
              />
              <span v-else-if="isHtml" v-html="row[prop]" />
              <span v-else-if="displayProp">{{
                row[displayProp]| mapArray(sep)| mapDefault
              }}</span>
              <!--使用枚举格式化数组字段信息-->
              <span v-else-if="enums && Array.isArray(row[prop])">
                {{ listEnumsValue(enums, row[prop]) }}
              </span>
              <!--使用枚举显示字段信息-->
              <span v-else-if="enums">
                {{ getEnumsValue(enums, row[prop]) }}
              </span>
              <!--默认显示-->
              <span v-else>{{ row[prop] | mapArray | mapDefault }}</span>
            </el-form-item>
          </template>
        </el-form>
      </el-table-column>
      <template
        v-for="{
          prop,
          props,
          type,
          label,
          isExpand,
          enums,
          disabled,
          displayProp,
          listComponent,
          isHtml,
          sortable,
          isImage,
          sep,
          width,
          isOverflow,
          placeholder,
          headComponent,
          ...arg
        } in configs"
      >
        <el-table-column
          v-if="!isExpand"
          :key="prop"
          v-bind="arg"
          :label="label"
          :align="align"
          :sortable="sortable"
          :width="isImage ? width ? width: 71 : width"
          :prop="prop"
        >
          <template v-if="headComponent" slot="header">
            <component
              :is="headComponent"
              :prop="prop"
              v-bind="{
                ...$attrs,
                ...arg
              }"
            />
          </template>
          <template slot-scope="{ row, $index }">
            <component
              :is="listComponent"
              v-if="listComponent"
              v-model="row[prop]"
              :data="row"
              :prop="prop"
              :enums="enums"
              v-bind="{
                ...$attrs,
                ...arg
              }"
            />
            <el-select
              v-else-if="type === 'edit-select' && enums"
              v-model="row[prop]"
              filterable
              :collapse-tags="!arg.notCollapseTags"
              :disabled="disabled"
              :placeholder="placeholder || `请选择${label}`"
              @change="handleEdit($index, row)"
            >
              <el-option
                v-for="{ label: eLabel, value } in enums"
                :key="value"
                :value="value"
                :label="eLabel"
              />
            </el-select>
            <el-input
              v-else-if="type === 'edit-input'"
              v-model="row[prop]"
              size="small"
              :disabled="disabled"
              :placeholder="placeholder || `请输入${label}`"
              @change="handleEdit($index, row)"
            />
            <el-image
              v-else-if="isImage && row[prop]"
              style="width: 50px;height:50px;"
              :src="row[prop]"
              :alt="label"
            />
            <span v-else-if="['datetime', 'date', 'datetimerange'].includes(type)">
              {{ row[prop] | mapTimer | mapDefault }}
            </span>
            <span v-else-if="isHtml" v-html="row[prop]" />
            <!--使用枚举格式化数组字段信息-->
            <span v-else-if="displayProp">{{
              row[displayProp]| mapArray(sep)| mapDefault
            }}</span>
            <span v-else-if="enums && Array.isArray(row[prop])">
              {{ listEnumsValue(enums, row[prop], sep) | mapDefault }}
            </span>
            <!--使用枚举显示字段信息-->
            <span v-else-if="enums">
              {{ getEnumsValue(enums, row[prop]) | mapDefault }}
            </span>
            <span v-else-if="props && row[prop]">{{
              row[prop][props] | mapArray | mapDefault
            }}</span>
            <!-- 自定义显示 -->
            <span v-else-if="arg.slotName">
              <slot :name="prop" :scope="row" />
            </span>
            <!--默认显示-->
            <span v-else :class="{ 'text-ellipsis-2': isOverflow }" :title="row[prop]">{{
              row[prop] | mapArray | mapDefault
            }}</span>
          </template>
        </el-table-column>
      </template>
      <!-- 额外的列 -->
      <slot />
      <template slot="empty">
        <slot name="empty" />
      </template>
      <template slot="append">
        <slot name="append" />
      </template>
    </el-table>
  </div>
</template>

<script>
import { isNil } from 'lodash'
import GetEnumsValueMixin from 'modules/mixins/get-enums-value'
import FilterList from 'modules/mixins/filter-list'
import TableHeader from './components/TableHeader.vue'

export default {
  name: 'TableListTemplate',
  components: {
    TableHeader
  },
  mixins: [GetEnumsValueMixin, FilterList],
  props: {
    configs: {
      type: Array,
      default() {
        return []
      }
    },
    datas: {
      type: Array,
      default() {
        return []
      }
    },
    border: {
      type: Boolean,
      default: true
    },
    height: {
      type: [Number, String],
      default: null
    },
    size: {
      // medium / small / mini
      type: String,
      default: ''
    },
    spanMethod: {
      type: Function,
      default() {
        return () => {}
      }
    },
    maxHeight: {
      type: Number,
      default: null
    },
    align: {
      type: String,
      default: 'left'
    },
    expand: Boolean,
    isOrderNumber: Boolean,
    selection: Boolean,
    selectable: {
      type: Function,
      default() {
        return () => true
      }
    },
    loading: Boolean,
    stripe: Boolean,
    showTableHeader: Boolean,
    needMarkProp: {
      // medium / small / mini
      type: String,
      default: 'status'
    },
    needMarkPropVal: {
      // medium / small / mini
      type: [Number, String],
      default: 0
    }
  },
  data() {
    return {
      currentSize: 'medium'
    }
  },
  computed: {
    hasExpandItem() {
      const config = this.configs || []
      return this.expand || config.some(list => list.isExpand)
    },
    tableSize() {
      return this.size || this.currentSize
    }
  },
  methods: {
    handleSortChange({ column, order }) {
      if (isNil(column) || isNil(order)) return
      const config = this.configs.find(({ label }) => column.label === label)
      this.$emit('sort-change', {
        prop: config.prop,
        order
      })
    },
    handleSelectionChange(row) {
      this.$emit('selection-change', row)
    },
    setTableSize(value) {
      this.currentSize = value
    },
    handleEdit(index, row) {
      console.log(index, row)
      this.$emit('handle-edit', { index: index, row: row })
    },
    markRow({ row }) {
      if (row[this.needMarkProp] === this.needMarkPropVal) {
        return 'mark-row'
      } else {
        return ''
      }
    }
  }
}
</script>

<style lang="scss">
.el-tooltip__popper {
  max-width: 500px;
}
.el-tooltip__popper,
.el-tooltip__popper.is-dark {
  background: rgb(48, 65, 86) !important;
  color: #fff;
  line-height: 24px;
}
.mark-row {
  color: rgba(#000, 0.3);
  td {
    background-color: #e3e3e3 !important;
  }
}
</style>
<style scoped>
.table-btn {
  display: flex;
  margin-bottom: 24px;
  justify-content: flex-end;
}
</style>
